Categories
JavaScript Best Practices

JavaScript Best Practices — With, Promise Errors, Regex Issues

Spread the love

JavaScript is a very forgiving language. It’s easy to write code that runs but has mistakes in it.

In this article, we look at issues with the with statement, named capture groups, rejecting errors with Error object, and using regex literals instead of the RegExp object.

Remove with Statements

with statements are bad. They let us add member objects to the current scope, which makes it impossible to tell what the variable inside the block refers to.

For instance, if we have the following code:

const obj = {
  a: 1,
  b: 2
};

with(obj) {
  a = 3;
}

Then the code is within the with block is written relative to the obj object. So a inside the block is actually referencing obj.a .

However, we can also declare new variables as follows:

const obj = {
  a: 1,
  b: 2
};

with(obj) {
  let a = 3;
}

which is block-scoped and can’t be accessed outside the with block.

Or we can declare a variable with var as follows:

const obj = {
  a: 1,
  b: 2
};

with(obj) {
  var a = 3;
}

which changes obj.a to 3.

As we can see the scope and of a varies depending on how we declared the variable inside with . We’re either modify the obj object’s properties or we’re declaring a new block-scoped variable if we use let or const .

Therefore, the with block is confusing and shouldn’t be used in our production code.

It doesn’t make writing our code easier, and it just makes our code more confusing to everyone.

Therefore, it should never be used in our code.

Use Named Capture Group in a Regular Expression

Named capture groups are good in regular expressions because it’s clear that where the capture groups are and what they’re checking for.

For instance, we can write something like the following:

const regex = /(?<email>[^@]+@[^.]+..+)/;

In the code above, we have a capture group called email that has the email regex after it.

Now instead of just having a bunch of symbols in our regex, we know that our regex capture group is checking for an email address.

Then we can retrieve the result of the capture group by using the exec method as follows:

const result = regex.exec('abc@abc.com').groups.email;

As we can see, the groups property of the object that’s returned by exec has the email property which has the match for our email capture group.

This is much better than just having a bunch of symbols without a name. We can’t get those with a named property.

Use Error Objects as Promise Rejection Reasons

Using error objects as promise rejection reasons is a good idea because it automatically stores the stack trace.

The stack trace is useful for debugging issues that caused the error since it tells us what functions are called to get to the final error.

If we don’t reject an error, then we have no stack trace and we don’t know what’s been called before the error.

For instance, instead of writing:

Promise.reject('error');

We should write:

Promise.reject(new Error('error'));

If we run both and look at the console log output, we’ll see that the 2nd example has the stack trace in the console log output and the first one doesn’t.

Use Regular Expressions Literals instead of the RegExp Constructor

In JavaScript, there’re 2 ways to construct regexes. One is the regular expression literals like /foo/ . The other way is to create an RegExp instance like new RegExp('foo');

Regular expressions are shorter and we can’t generate a regex dynamically with literals. The RegExp constructor takes a string with the regex that we want to create, so we can create a regex dynamically with a string.

However, if we want to add escape characters with the RegExp constructor, we’ve to add an extra backslash before the escape character so that we can write the escape character in the regex string as follows:

new RegEx('d+$');

Because of the extra complexity, it’s better to use regex literals instead of using the RegExp constructor. The regex above would be the same as:

/d+$/

if it’s written as a regex literal.

Conclusion

with statements should never be used in our code since it changes the scope of the variables inside.

Error objects should be used to reject promises so that we get a stack trace in our console log.

If we construct regexes, we should use the regex literals as it’s simpler. Named capture groups should be used so that we can retrieve the capture group match with a name and also makes the pattern easier to understand.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *